
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"

#include "esp_log.h"
#include "esp_system.h"
#include "esp_freertos_hooks.h"

#include "lvgl.h"
#include "lvgl_helpers.h"
#include "ui.h"
#include "ui_helpers.h"

/*-----------------函数声明-----------------------------------*/
void lvgl_test(void);
static void lv_tick_task(void);
static void gui_task(void *arg);
/*-----------------------------------------------------------*/

/*-----------------全局变量声明------------------------------*/
static SemaphoreHandle_t xGuiSemaphore;
/*----------------------------------------------------------*/

/**
 * @brief      主函数
 * 
 */
void app_main(void)
{
    xTaskCreatePinnedToCore(gui_task, "gui task", 1024 * 3, NULL, 1, NULL, 1);
}

/**
 * @brief      ui界面任务
 * 
 * @param[in]  arg                 创建任务时传递的参数
 */
static void gui_task(void *arg)
{
    xGuiSemaphore = xSemaphoreCreateMutex(); // 建立互斥量

    /*************初始化*******************/
    lv_init();          // lvgl内核初始化
    lvgl_driver_init(); // lvgl显示\输入硬件初始化（系统内预定义硬件）

    /*************建立双缓冲*******************/
 	static lv_disp_draw_buf_t draw_buf;
    lv_color_t *buf1 = heap_caps_malloc(DISP_BUF_SIZE * sizeof(lv_color_t), MALLOC_CAP_DMA);
    lv_color_t *buf2 = heap_caps_malloc(DISP_BUF_SIZE * sizeof(lv_color_t), MALLOC_CAP_DMA);
    lv_disp_draw_buf_init(&draw_buf, buf1, buf2, DISP_BUF_SIZE ); //初始化显示用缓存

    /***************显示器驱动及显示器句柄****************/
    static lv_disp_drv_t disp_drv;         // 显示驱动的句柄，必须是静态的
    lv_disp_drv_init(&disp_drv);           // 显示驱动的初始化
    disp_drv.draw_buf = &draw_buf;         // 将渲染buff分配给显示驱动
    disp_drv.flush_cb = disp_driver_flush; // 默认回调函数
    disp_drv.hor_res = 320;                // 设定屏幕的水平宽度
    disp_drv.ver_res = 240;                // 设定屏幕垂直高度
    lv_disp_drv_register(&disp_drv);       // 注册显示驱动--创建三层级screen

    /***************输入设备驱动及驱动句柄****************/
    static lv_indev_drv_t indev_drv;
    lv_indev_drv_init(&indev_drv);
    indev_drv.type = LV_INDEV_TYPE_POINTER;
    indev_drv.read_cb = touch_driver_read;
    lv_indev_t * my_indev = lv_indev_drv_register(&indev_drv);

    /* 注册freertos的系统滴答钩子函数，系统没执行一个时时间片，则执行一次 */
    esp_register_freertos_tick_hook(lv_tick_task);

    /**********ui布局**********/
    ui_init();

    /*******周期性执行屏幕处理任务*********************/
    while (1)
    {
        /* 一个时间片处理一次 */
        vTaskDelay(1);
        if (pdTRUE == xSemaphoreTake(xGuiSemaphore, portMAX_DELAY))
        {
            lv_timer_handler();
            xSemaphoreGive(xGuiSemaphore);
        }
    }
}


/****系统的时间基准，每一个时间片（10ms）告诉系统一次***********************/
static void lv_tick_task(void)
{
    lv_tick_inc(10);
}
